package org.andolphin.client;

import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.andolphin.client.Andolphin.Prefs;
import org.andolphin.client.model.Payment;
import org.andolphin.client.provider.PaymentColumns;
import org.andolphin.client.utils.DateUtils;
import org.andolphin.client.utils.StringUtils;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemLongClickListener;

public class PaymentActivity extends Activity implements OnDateSetListener, OnItemLongClickListener {
    /**
     * 错误消息
     */
    String errorMessage;
    /**
     * 日期显示
     */
    TextView dateView;
    /**
     * 下一天按钮
     */
    ImageButton nextBtn;
    /**
     * 上一天按钮
     */
    ImageButton prevBtn;
    static final SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
    Date queryDate;
    static final int DIALOG_ID_DATE = 0;
    static final int DIALOG_ID_ADD = 1;
    static final int DIALOG_ID_ERROR_INPUT = 2;
    static final int DIALOG_ID_INFO = 4;
    static final int DIALOG_ID_EDIT = 3;
    EditText amountEdit;
    AutoCompleteTextView categoryEdit;
    EditText descriptionEdit;
    RadioGroup balanceRadioGroup;
    ListView todayList;
    ListAdapter adapter;
    TextView statusView;
    Payment currentPayment;

    /**
     * 数值格式
     */
    static final NumberFormat nf;
    static {
        nf = NumberFormat.getInstance();
        nf.setMaximumFractionDigits(2);
        nf.setMinimumFractionDigits(2);
    }

    static class ListAdapter extends CursorAdapter {
        ListView parent;
        TextView status;
        LayoutInflater inflater;
        Context context;

        public ListAdapter(Context context, ListView parent, TextView status, Cursor c) {
            super(context, c);
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            this.parent = parent;
            this.status = status;
            this.context = context;
            if (c == null || c.getCount() == 0) {
                status.setText(context.getResources().getString(R.string.payment_empty));
            } else {
                status.setText(context.getResources().getString(R.string.payment_count, new Object[] { c.getCount() }));
            }
        }

        @Override
        public void changeCursor(Cursor cursor) {
            if (cursor == null || cursor.getCount() == 0) {
                status.setText(this.context.getResources().getString(R.string.payment_empty));
            } else {
                status.setText(context.getResources().getString(R.string.payment_count,
                        new Object[] { cursor.getCount() }));
            }
            super.changeCursor(cursor);
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            if (cursor != null) {
                setValue(view, cursor);
            }
        }

        private void setValue(View view, Cursor cursor) {
            double amount = cursor.getDouble(cursor.getColumnIndex(PaymentColumns.COL_AMOUNT));
            TextView amountView = (TextView) view.findViewById(R.id.tv_payment_list_amount);
            amountView.setText(nf.format(amount));
            String category = cursor.getString(cursor.getColumnIndex(PaymentColumns.COL_CATEGORY));
            TextView categoryView = (TextView) view.findViewById(R.id.tv_payment_list_category);
            categoryView.setText(category);
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            return inflater.inflate(R.layout.payment_list_item, parent, false);
        }

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.checkRegister();

        queryDate = DateUtils.now();

        changeViewToList();
        queryDateChanged();
    }

    /**
     * 检查注册信息
     */
    private void checkRegister() {
        SharedPreferences prefs = this.getSharedPreferences(Andolphin.Prefs.ANDOLPHIN, Prefs.MODE);
        String username = prefs.getString(Andolphin.Prefs.USERNAME, null);
        String password = prefs.getString(Andolphin.Prefs.PASSWORD, null);
        long expire = prefs.getLong(Andolphin.Prefs.EXPIRE, -1);

        if (username == null || password == null) {
            Intent intent = new Intent(Andolphin.Intent.LOGIN);
            intent.addCategory(Intent.CATEGORY_DEFAULT);
            this.startActivity(intent);
        } else {
            if (DateUtils.nowInMillis() >= expire) {
                Toast.makeText(this, "expired", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.payment, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        super.onOptionsItemSelected(item);
        switch (item.getItemId()) {
        case R.id.payment_add:
            showDialog(DIALOG_ID_ADD);
            break;
        case R.id.payment_sync:
            doSync();
            break;
        case R.id.payment_cfg:
            break;
        case R.id.payment_month:
            break;
        }
        return false;
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        AlertDialog.Builder builder;
        switch (id) {
        case DIALOG_ID_DATE:
            return new DatePickerDialog(this, this, DateUtils.getYear(queryDate), DateUtils.getMonth(queryDate),
                    DateUtils.getDay(queryDate));
        case DIALOG_ID_INFO:
            builder = new AlertDialog.Builder(this);
            builder.setTitle(getResources().getString(R.string.info));
            builder.setIcon(getResources().getDrawable(R.drawable.information));
            builder.setMessage("");
            builder.setCancelable(false).setPositiveButton(getResources().getString(R.string.ok),
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    });
            return builder.create();
        case DIALOG_ID_ERROR_INPUT:
            builder = new AlertDialog.Builder(this);
            builder.setTitle(getResources().getString(R.string.input_error));
            builder.setIcon(getResources().getDrawable(R.drawable.exclamation));
            builder.setMessage("");
            builder.setCancelable(false).setPositiveButton(getResources().getString(R.string.ok),
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    });
            return builder.create();
        case DIALOG_ID_EDIT:
            builder = new AlertDialog.Builder(this);
            builder.setTitle(getResources().getString(R.string.payment_edit));
            builder.setMessage("");
            builder.setCancelable(false).setPositiveButton(getResources().getString(R.string.edit),
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            showEditView();
                        }
                    }).setNeutralButton(getResources().getString(R.string.delete),
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            doDelete();
                        }
                    }).setNegativeButton(getResources().getString(R.string.cancel),
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    });

            builder.setIcon(getResources().getDrawable(R.drawable.exclamation));
            return builder.create();
        case DIALOG_ID_ADD:
            LayoutInflater inflater = getLayoutInflater();
            View layout = inflater.inflate(R.layout.payment_add, (ViewGroup) findViewById(R.id.payment_add_root));
            balanceRadioGroup = (RadioGroup) layout.findViewById(R.id.rd_balance);
            amountEdit = (EditText) layout.findViewById(R.id.edit_payment_amount);
            categoryEdit = (AutoCompleteTextView) layout.findViewById(R.id.edit_payment_category);
            descriptionEdit = (EditText) layout.findViewById(R.id.edit_payment_description);
            builder = new AlertDialog.Builder(this);
            builder.setTitle(getResources().getString(R.string.payment_add));
            builder.setPositiveButton(getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    addPayment();
                }
            });
            builder.setNegativeButton(getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });
            builder.setView(layout);
            return builder.create();
        default:
            return super.onCreateDialog(id);
        }
    }

    protected void addPayment() {
        String amount = amountEdit.getText().toString();
        if (!StringUtils.isDouble(amount)) {
            this.errorMessage = getResources().getString(R.string.msg_amount_invalid);
            showDialog(DIALOG_ID_ERROR_INPUT);
        } else {
            ContentValues values = new ContentValues();
            values.put(PaymentColumns.COL_AMOUNT, Double.parseDouble(amount));
            if (balanceRadioGroup.getCheckedRadioButtonId() == R.id.rd_balance_expenditure) {
                values.put(PaymentColumns.COL_BALANCE, Payment.VAL_EXPENDITURE);
            } else {
                values.put(PaymentColumns.COL_BALANCE, Payment.VAL_INCOME);
            }
            values.put(PaymentColumns.COL_CATEGORY, categoryEdit.getText().toString());
            values.put(PaymentColumns.COL_DESCRIPTION, descriptionEdit.getText().toString());
            values.put(PaymentColumns.COL_EVENT_DATE, DateUtils.formatDate(queryDate));
            Uri uri = getContentResolver().insert(PaymentColumns.CONTENT_URI, values);
            queryDateChanged();
        }
    }

    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        switch (id) {
        case DIALOG_ID_DATE:
            DatePickerDialog d1 = (DatePickerDialog) dialog;
            d1.updateDate(DateUtils.getYear(queryDate), DateUtils.getMonth(queryDate), DateUtils.getDay(queryDate));
            break;
        case DIALOG_ID_ERROR_INPUT:
            ((AlertDialog) dialog).setMessage(this.errorMessage);
            break;
        case DIALOG_ID_EDIT:
            ((AlertDialog) dialog).setMessage(this.errorMessage);
            break;
        case DIALOG_ID_ADD:
            balanceRadioGroup.check(R.id.rd_balance_expenditure);
            break;
        default:
            super.onPrepareDialog(id, dialog);
        }
    }

    private void doSync() {
        
    }

    protected void doDelete() {
        Uri uri = ContentUris.withAppendedId(PaymentColumns.CONTENT_URI, currentPayment.getId());
        getContentResolver().delete(uri, null, null);
        queryDateChanged();
    }

    protected void showEditView() {
        Uri uri = ContentUris.withAppendedId(PaymentColumns.CONTENT_URI, currentPayment.getId());
        Cursor cur = getContentResolver().query(uri, null, null, null, null);
        if (cur != null && cur.getCount() != 0 && cur.moveToFirst()) {
            currentPayment = new Payment();
            currentPayment.fromCursor(cur);
            changeViewToEdit();
        }

    }

    protected void queryDateChanged() {
        this.dateView.setText(df.format(queryDate));
        Uri uri = Uri.withAppendedPath(PaymentColumns.CONTENT_URI, "date");
        uri = Uri.withAppendedPath(uri, DateUtils.formatDate(queryDate));
        Cursor cur = getContentResolver().query(uri, null, null, null, null);
        adapter.changeCursor(cur);
    }

    public void onDateSet(DatePicker view, int year, int month, int day) {
        this.queryDate = DateUtils.getDate(year, month, day);
        this.queryDateChanged();
    }

    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        Cursor cur = (Cursor) parent.getAdapter().getItem(position);
        currentPayment = new Payment();
        currentPayment.fromCursor(cur);
        TextView amountText = (TextView) view.findViewById(R.id.tv_payment_list_amount);
        TextView categoryText = (TextView) view.findViewById(R.id.tv_payment_list_category);
        this.errorMessage = amountText.getText() + ":" + categoryText.getText();
        showDialog(DIALOG_ID_EDIT);
        return false;
    }

    /**
     * 切换成列表画面
     */
    protected void changeViewToList() {
        setContentView(R.layout.payment);

        this.dateView = (TextView) findViewById(R.id.tv_payment_date);
        this.dateView.setText(df.format(queryDate));
        this.dateView.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                PaymentActivity.this.showDialog(DIALOG_ID_DATE);
            }
        });

        this.nextBtn = (ImageButton) findViewById(R.id.btn_payment_next);
        this.nextBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                queryDate = DateUtils.addDay(queryDate, 1);
                PaymentActivity.this.queryDateChanged();
            }
        });

        this.prevBtn = (ImageButton) findViewById(R.id.btn_payment_prev);
        this.prevBtn.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                queryDate = DateUtils.addDay(queryDate, -1);
                PaymentActivity.this.queryDateChanged();
            }
        });

        statusView = (TextView) findViewById(R.id.tv_payment_list_status);

        todayList = (ListView) findViewById(R.id.list_today_payments);
        adapter = new ListAdapter(this, todayList, statusView, null);
        todayList.setAdapter(adapter);
        todayList.setOnItemLongClickListener(this);
    }

    /**
     * 切换成编辑画面
     */
    protected void changeViewToEdit() {
        setContentView(R.layout.payment_edit);

        double amount = currentPayment.getAmount().doubleValue();
        String categroy = currentPayment.getCategory();
        String balance = currentPayment.getBalance();
        String description = currentPayment.getDescription();

        final EditText amountEdit = (EditText) findViewById(R.id.edit_payment_amount);
        amountEdit.setText(nf.format(amount));

        final EditText categoryEdit = (EditText) findViewById(R.id.edit_payment_category);
        categoryEdit.setText(categroy);

        final EditText descriptionEdit = (EditText) findViewById(R.id.edit_payment_description);
        descriptionEdit.setText(description);

        final RadioGroup balanceRadioGroup = (RadioGroup) findViewById(R.id.rd_balance);
        if (Payment.VAL_EXPENDITURE.equals(balance)) {
            balanceRadioGroup.check(R.id.rd_balance_expenditure);
        } else if (Payment.VAL_INCOME.equals(balance)) {
            balanceRadioGroup.check(R.id.rd_balance_income);
        }

        Button cancelBtn = (Button) findViewById(R.id.btn_cancel);
        cancelBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                PaymentActivity.this.changeViewToList();
                PaymentActivity.this.queryDateChanged();
            }
        });

        Button okBtn = (Button) findViewById(R.id.btn_ok);
        okBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                String amount = amountEdit.getText().toString();
                if (!StringUtils.isDouble(amount)) {
                    PaymentActivity.this.errorMessage = getResources().getString(R.string.msg_amount_invalid);
                    PaymentActivity.this.showDialog(DIALOG_ID_ERROR_INPUT);
                } else {
                    ContentValues values = new ContentValues();
                    values.put(PaymentColumns.COL_AMOUNT, Double.parseDouble(amount));
                    if (balanceRadioGroup.getCheckedRadioButtonId() == R.id.rd_balance_expenditure) {
                        values.put(PaymentColumns.COL_BALANCE, Payment.VAL_EXPENDITURE);
                    } else {
                        values.put(PaymentColumns.COL_BALANCE, Payment.VAL_INCOME);
                    }
                    values.put(PaymentColumns.COL_CATEGORY, categoryEdit.getText().toString());
                    values.put(PaymentColumns.COL_DESCRIPTION, descriptionEdit.getText().toString());
                    String selection = PaymentColumns.COL_LAST_UPDATED + "= ?";
                    Uri uri = ContentUris.withAppendedId(PaymentColumns.CONTENT_URI, currentPayment.getId());
                    int count = getContentResolver().update(uri, values, selection,
                            new String[] { DateUtils.formatDateTime(currentPayment.getLastUpdated()) });
                    if (count == 0) {
                        PaymentActivity.this.errorMessage = getResources().getString(R.string.msg_update_failure);
                        PaymentActivity.this.showDialog(DIALOG_ID_INFO);
                    } else {
                        PaymentActivity.this.changeViewToList();
                        PaymentActivity.this.queryDateChanged();
                        Toast.makeText(PaymentActivity.this, getResources().getString(R.string.msg_update_success),
                                Toast.LENGTH_SHORT).show();
                    }

                }
            }
        });
    }

}